home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / PowerPlant / UWindowUsher 1.1 / UWindowsUsher.cp < prev    next >
Text File  |  1995-08-28  |  20KB  |  783 lines

  1. // ===========================================================================
  2. //    UWindowsUsher.cp                © 1995, Éric Forget. All rights reserved.
  3. // ===========================================================================
  4. //    
  5. //    ************************************************************************
  6. //    *                                                                      *
  7. //    *    Before using this code you should read the "License Agreement"     *
  8. //    *    document and agree with it.                                        *
  9. //    *                                                                      *
  10. //    ************************************************************************
  11. //
  12. //
  13. //    This module try to place your windows to their *right* place!
  14. //    It also manage your Window menu.
  15. //
  16. //    In version 1.1, UWindowUsher now deal correctly with standard size.
  17. //
  18. // ---------------------------------------------------------------------------
  19. //
  20. //    Instruction Notes:
  21. //    -----------------
  22. //
  23. //    1)    Add this line in your CXXXApp (Application class) constructor:
  24. //
  25. //                UWindowsUsher::Initialize();
  26. //    
  27. //        *OR* this line if you have a Window Menu:
  28. //
  29. //                UWindowsUsher::Initialize(myWindowMenuID);
  30. //
  31. //
  32. //    2)    Add this line of code where you create your document’s window:
  33. //
  34. //                UWindowsUsher::AddWindow(myLWindow, myShowIt);
  35. //    
  36. //        *OR* this line if you want modified document to be underlined:
  37. //
  38. //                UWindowsUsher::AddWindow(myLWindow, myShowIt, this);
  39. //
  40. //
  41. //    3)    Add this line of code where you delete your document’s window:
  42. //
  43. //                UWindowsUsher::RemoveWindow(myLWindow);
  44. //
  45. //
  46. //    4)    Normally, use the command number 30 to your Stack Windows item.
  47. //        If you do this, it will be enabled and disabled automatically. 
  48. //        To do this put use the 'Mcmd' resource. But, optionally you
  49. //        may call directly:
  50. //
  51. //                UWindowsUsher::Stack();
  52. //
  53. //
  54. //    5)    That’s all. If you have problems, find a bug (hopefully not!)
  55. //        or if you just like it, drop me a message at my e-mail address: 
  56. //
  57. //                ForgetE@eWorld.com
  58. //
  59. //
  60. // ---------------------------------------------------------------------------
  61. //
  62. //    Usage Notes: 
  63. //    -----------
  64. //    
  65. //    1)    (from UDesktop.cp)
  66. //        You must call UScreenPort::Initialize() before using this
  67. //        class. Since you only need to call it once, the best place
  68. //        to call UScreenPort::Initialize() is in the constructor for
  69. //        your Application class.
  70. //
  71. //    2)    You must call UWindowsUsher::Dispose() before exiting a code resource
  72. //        if you don’t need the leak… :-)
  73. //
  74. //    3)    I have use a command reserved for the cmd_StackWindows in hoping
  75. //        that MetroWerks will add it to their *reserved* list...
  76. //
  77. // ---------------------------------------------------------------------------
  78.  
  79. #ifdef PowerPlant_PCH
  80. #include PowerPlant_PCH
  81. #endif
  82.  
  83. #include    "UWindowsUsher.h"
  84. #include    <LAttachable.h>
  85. #include    <LCommander.h>
  86. #include    <LDocument.h>
  87. #include    <LMenu.h>
  88. #include    <LMenuBar.h>
  89. #include    <LList.h>
  90. #include     <LWindow.h>
  91. #include    <String_Utils.h>
  92. #include    <UDrawingState.h>
  93. #include     <UScreenPort.h>
  94.  
  95. #ifndef __RESOURCES__
  96. #include <Resources.h>
  97. #endif
  98.  
  99. #ifndef __LOWMEM__
  100. #include <LowMem.h>
  101. #endif
  102.  
  103. #ifndef __TOOLUTILS__
  104. #include <ToolUtils.h>
  105. #endif
  106.  
  107. #ifndef __ERRORS__
  108. #include <Errors.h>
  109. #endif
  110.  
  111. #ifndef __MENUS__
  112. #include <Menus.h>
  113. #endif
  114.  
  115.  
  116. // ---------------------------------------------------------------------------
  117. //        • Static Member Variable 
  118. // ---------------------------------------------------------------------------
  119.  
  120. LList            *UWindowsUsher::sWindowList            = nil;
  121. LList            *UWindowsUsher::sAttachmentList        = nil;
  122. ResIDT            UWindowsUsher::sWindowMenuID        = Menu_Undefined;
  123. LCommander        *UWindowsUsher::sApplication        = nil;
  124. LAttachment        *UWindowsUsher::sStackAttachment    = nil;
  125.  
  126.  
  127. // ---------------------------------------------------------------------------
  128. //        • Constants
  129. // ---------------------------------------------------------------------------
  130.  
  131. const    Int16    Int16_LeftShift            = 5;
  132. const    Int16    Int16_TopShift            = 18;
  133. const    Int16    Int16_BottomShift        = 5;
  134. const    Int16    Int16_RightShift        = 5;
  135. const    Int16    Int16_TopMargin            = 5;
  136. const    Int16    Int16_RightMargin        = 80;
  137. const    Int16    Int16_BottomMargin        = 30;
  138. const    Int16    Int16_WindowsCount        = 5;
  139.  
  140.  
  141.  
  142. // ===========================================================================
  143. // • UWindowsUsher                                               UWindowsUsher •
  144. // ===========================================================================
  145.  
  146. // ---------------------------------------------------------------------------
  147. //        • Initialize
  148. // ---------------------------------------------------------------------------
  149.  
  150. void
  151. UWindowsUsher::Initialize(
  152.     ResIDT            inWindowMenuID)
  153. {
  154.     if (sWindowList != nil)    {        // Do nothing if already initialized
  155.         return;
  156.     }
  157.     
  158.     
  159.     if((sWindowMenuID = inWindowMenuID) != Menu_Undefined) {
  160.     
  161.         // Find the Super Commander of all!
  162.         LCommander    *tempTarget = LCommander::GetTarget();
  163.         
  164.         while(tempTarget != nil) {
  165.             
  166.             sApplication = tempTarget;
  167.             tempTarget = sApplication->GetSuperCommander();
  168.         }
  169.         
  170.         sAttachmentList = new LList(sizeof(LAttachment *));
  171.         
  172.         sStackAttachment = new LStackCmdAttachment();
  173.     }
  174.     
  175.     
  176.     
  177.     // Allocate the window list
  178.     sWindowList = new LList(sizeof(LWindow *));
  179. }
  180.  
  181.  
  182. // ---------------------------------------------------------------------------
  183. //        • Dispose
  184. // ---------------------------------------------------------------------------
  185.  
  186. void
  187. UWindowsUsher::Dispose()
  188. {
  189.     if (sWindowList == nil)    {        // Do nothing if not initialized
  190.         return;
  191.     }
  192.     
  193.     // Delete the window list
  194.     delete sWindowList;
  195.     sWindowList = nil;
  196.     
  197.     if(sApplication != nil) {
  198.     
  199.         if(sStackAttachment != nil) {
  200.         
  201.             sApplication->RemoveAttachment(sStackAttachment);
  202.             delete sStackAttachment;
  203.         }
  204.     }
  205.     
  206.     if(sAttachmentList != nil) {
  207.     
  208.         delete sAttachmentList;
  209.     }
  210. }
  211.  
  212.  
  213. // ---------------------------------------------------------------------------
  214. //        • AddWindow
  215. // ---------------------------------------------------------------------------
  216. //    Add the window to the list and stack it to the first empty place.
  217.  
  218. void
  219. UWindowsUsher::AddWindow(
  220.     LWindow        *inWindow,
  221.     Boolean        inShowIt,
  222.     LDocument    *inDocument)
  223. {
  224.     Assert_(sWindowList != nil);
  225.     Assert_(inWindow != nil);
  226.     Assert_(sWindowList->GetCount() <= max_Int16);    // Will you really add more than max_Int16?
  227.     
  228.     
  229.     LWindow        *dummyWindow = inWindow; // Could be initialize to any value except nil!
  230.     Int32         itemNo;
  231.     
  232.     volatile LWindowMenuAttachment    *anAttachment = nil;
  233.     
  234.     
  235.     Try_ {
  236.     
  237.         // Check for an empty slot...
  238.         for(itemNo = 1; (itemNo <= sWindowList->GetCount()) && (dummyWindow != nil); itemNo++) {
  239.         
  240.             sWindowList->FetchItemAt(itemNo, &dummyWindow);
  241.             
  242.             if(dummyWindow == nil) {
  243.             
  244.                 itemNo--;
  245.             }
  246.         }
  247.         
  248.         // Append the window or put it the empty slot...
  249.         if(itemNo > sWindowList->GetCount()) {
  250.         
  251.             sWindowList->InsertItemsAt(1, itemNo, &inWindow);
  252.         
  253.         } else {
  254.         
  255.             sWindowList->SetItemAt(itemNo, &inWindow);
  256.         }
  257.         
  258.         // Stack the window at its position...
  259.         StackAtPos(itemNo, inWindow);
  260.         
  261.         
  262.         // Add the window name to the Windows menu
  263.         if((sWindowMenuID != Menu_Undefined) && (sApplication != nil)) {
  264.         
  265.             anAttachment = new LWindowMenuAttachment(inWindow, sWindowMenuID, inDocument);
  266.             
  267.             sApplication->AddAttachment(anAttachment, nil, false);
  268.             
  269.             // Append the window or put it the empty slot...
  270.             if(itemNo > sAttachmentList->GetCount()) {
  271.             
  272.                 sAttachmentList->InsertItemsAt(1, itemNo, &anAttachment);
  273.             
  274.             } else {
  275.             
  276.                 sAttachmentList->SetItemAt(itemNo, &anAttachment);
  277.             }
  278.             
  279.             if(itemNo == 1) {
  280.             
  281.                 sApplication->AddAttachment(sStackAttachment, nil, false);
  282.             }
  283.         }
  284.     
  285.     } Catch_(inErr) {
  286.         
  287.         // if in a rare situation we have lacked RAM...
  288.         if(sAttachmentList != nil) {
  289.             
  290.             // sAttachmentList and sWindowList must have the same size!
  291.             if(sAttachmentList->GetCount() < sWindowList->GetCount()) {
  292.             
  293.                 sWindowList->RemoveItemsAt(1, sWindowList->GetCount());
  294.                 
  295.                 // a possible leak...
  296.                 if(anAttachment != nil) {
  297.                     
  298.                     delete anAttachment;
  299.                 }
  300.             }
  301.         }
  302.         
  303.     } EndCatch_
  304.     
  305.     // Show the window if necesary...
  306.     if(inShowIt) {
  307.     
  308.         inWindow->Show();
  309.     }
  310. }
  311.  
  312.  
  313. // ---------------------------------------------------------------------------
  314. //        • RemoveWindow
  315. // ---------------------------------------------------------------------------
  316. //    RemoveWindow the window from the list.
  317.  
  318. void
  319. UWindowsUsher::RemoveWindow(
  320.     LWindow        *inWindow)
  321. {
  322.     Assert_(sWindowList != nil);
  323.     Assert_(inWindow != nil);
  324.     
  325.     Int32    index = sWindowList->FetchIndexOf(&inWindow);
  326.     Int32    dummyPtr = nil;
  327.     
  328.     
  329.     Assert_(index); // Hey, it would be faster in release version if I it doesn’t
  330.                     // have to check for this...
  331.     
  332.     dummyPtr = nil;
  333.     sWindowList->SetItemAt(index, &dummyPtr);
  334.         
  335.     if(index == sWindowList->GetCount()) {
  336.         
  337.         // It was the last so remove it...
  338.         // ...and all empty slots at the end
  339.         do {
  340.         
  341.             sWindowList->FetchItemAt(sWindowList->GetCount(), &dummyPtr);
  342.             
  343.             if(dummyPtr == nil) {
  344.             
  345.                 sWindowList->RemoveItemsAt(1, sWindowList->GetCount());
  346.             }
  347.             
  348.         } while((dummyPtr == nil) && sWindowList->GetCount());
  349.     }
  350.     
  351.     if((sWindowList->GetCount() == 0) && (sApplication != nil)) {
  352.     
  353.         sApplication->RemoveAttachment(sStackAttachment);
  354.     }
  355.     
  356.     
  357.     if((sWindowMenuID != Menu_Undefined) && (sApplication != nil)) {
  358.         
  359.         LWindowMenuAttachment    *anAttachment;
  360.         CommandT                cmdRemoved;
  361.         
  362.         
  363.         sAttachmentList->FetchItemAt(index, &anAttachment);
  364.         
  365.         dummyPtr = nil;
  366.         sAttachmentList->SetItemAt(index, &dummyPtr);
  367.                 
  368.         if(index == sAttachmentList->GetCount()) {
  369.             
  370.             // It was the last so remove it...
  371.             // ...and all empty slots at the end
  372.             do {
  373.             
  374.                 sAttachmentList->FetchItemAt(sAttachmentList->GetCount(), &dummyPtr);
  375.                 
  376.                 if(dummyPtr == nil) {
  377.                 
  378.                     sAttachmentList->RemoveItemsAt(1, sAttachmentList->GetCount());
  379.                 }
  380.                 
  381.             } while((dummyPtr == nil) && sWindowList->GetCount());
  382.         }
  383.         
  384.         if(anAttachment != nil) {    // We are never too careful!
  385.             
  386.             sApplication->RemoveAttachment(anAttachment);
  387.             
  388.             cmdRemoved = anAttachment->GetCommand();
  389.             delete anAttachment;
  390.             
  391.             // Tell all attachment that one of their pears has been removed...
  392.             LListIterator iterator(*sAttachmentList, iterate_FromStart);
  393.             while (iterator.Next(&anAttachment)) {
  394.                 
  395.                 if(anAttachment != nil) {
  396.                     
  397.                     anAttachment->AttachmentHasBeenRemoved(cmdRemoved);
  398.                 }
  399.             }
  400.         }
  401.         
  402.     }
  403. }
  404.  
  405.  
  406. // ---------------------------------------------------------------------------
  407. //        • GetWindowCount
  408. // ---------------------------------------------------------------------------
  409.  
  410. Int16
  411. UWindowsUsher::GetWindowCount()
  412. {
  413.     return sWindowList->GetCount();
  414. }
  415.  
  416.  
  417. // ---------------------------------------------------------------------------
  418. //        • IsStackEnabled
  419. // ---------------------------------------------------------------------------
  420. //    Return true if there is at least on window in the list...
  421.  
  422. Boolean
  423. UWindowsUsher::IsStackEnabled()
  424. {
  425.     return (sWindowList->GetCount() > 0) && (!UDesktop::FrontWindowIsModal());
  426. }
  427.  
  428.  
  429. // ---------------------------------------------------------------------------
  430. //        • Stack
  431. // ---------------------------------------------------------------------------
  432. //    Stack all windows.
  433.  
  434. void
  435. UWindowsUsher::Stack()
  436. {
  437.     Assert_(sWindowList != nil);
  438.     
  439.     Int32        windowNo = 1;
  440.     LWindow        *ppWindow = nil;
  441.     Int32        index;
  442.     WindowPtr    theWindowP;
  443.     CursHandle    watchCursorH;
  444.     Cursor        watchCopy;
  445.     
  446.     
  447.     // Change the cursor to the watch...
  448.     watchCursorH = ::GetCursor(watchCursor);
  449.     watchCopy = **watchCursorH;
  450.     ::SetCursor(&watchCopy);
  451.     
  452.     // For each slot in the list...
  453.     for(Int32 i = 1; i <= sWindowList->GetCount(); i++) {
  454.         
  455.         // ... find the right PowerPlant’s LWindow...
  456.         do {
  457.         
  458.             do {
  459.                 
  460.                 theWindowP = UWindows::FindNthWindow(windowNo++);
  461.                 ppWindow = LWindow::FetchWindowObject(theWindowP);
  462.             
  463.             } while((ppWindow == nil) && (theWindowP != nil));
  464.             
  465.             index = sWindowList->FetchIndexOf(&ppWindow);
  466.         
  467.         } while((index == arrayIndex_Bad) && (theWindowP != nil));
  468.         
  469.         // If we have find a good PowerPlant’s LWindow...
  470.         if((index != arrayIndex_Bad) && (ppWindow != nil)) {
  471.             
  472.             // We need to swap because windows order may have changed...
  473.             sWindowList->SwapItems(i, index);
  474.             sAttachmentList->SwapItems(i, index);
  475.             
  476.             // Do the job!
  477.             StackAtPos(i, ppWindow);
  478.         
  479.         }
  480.     }
  481.     
  482.     // Remove empty slots...
  483.     while(sWindowList->FetchItemAt(sWindowList->GetCount(), &ppWindow)) {
  484.     
  485.         if(ppWindow == nil) {
  486.             
  487.             // // Remove an empty slot...
  488.             sAttachmentList->RemoveItemsAt(1, sWindowList->GetCount());
  489.             sWindowList->RemoveItemsAt(1, sWindowList->GetCount());
  490.         
  491.         } else {
  492.         
  493.             break;    // All empty slot have been removed!
  494.         }
  495.     }
  496.     
  497.     ::SetCursor(&UQDGlobals::GetQDGlobals()->arrow);
  498. }
  499.  
  500.  
  501. // ---------------------------------------------------------------------------
  502. //         • StackAtPos
  503. // ---------------------------------------------------------------------------
  504. //    Stack a window.
  505.  
  506. void
  507. UWindowsUsher::StackAtPos(
  508.     Int16        inPos,
  509.     LWindow        *inWindow)
  510. {
  511.                     // Some tricky code to translate in five slots...
  512.     Int16            realPos = ((inPos - 1) % Int16_WindowsCount) + 1;
  513.     Rect            windowBounds = UScreenPort::GetScreenPort()->portRect;
  514.     SDimension16    stdSize;
  515.     Boolean            resizeable = inWindow->HasAttribute(windAttr_Resizable);
  516.     
  517.     
  518.     inWindow->GetStandardSize(stdSize); 
  519.     
  520.     // The magic code!
  521.     windowBounds.top += Int16_TopMargin + realPos * Int16_TopShift;
  522.     windowBounds.left += realPos * Int16_LeftShift;
  523.     if (resizeable && stdSize.height > windowBounds.bottom) {
  524.  
  525.         windowBounds.bottom -= Int16_BottomMargin - realPos * Int16_BottomShift;
  526.         
  527.     } else {
  528.     
  529.         windowBounds.bottom = windowBounds.top + stdSize.height;
  530.     }
  531.     
  532.      if (resizeable && stdSize.width > windowBounds.right) {
  533.  
  534.         windowBounds.right -= Int16_RightMargin - realPos * Int16_RightShift;
  535.      
  536.     } else {
  537.         
  538.         windowBounds.right = windowBounds.left + stdSize.width;
  539.         
  540.     }
  541.     
  542.     inWindow->DoSetBounds(windowBounds);
  543. }
  544.  
  545.  
  546. // ===========================================================================
  547. // • LWindowMenuAttachment                               LWindowMenuAttachment •
  548. // ===========================================================================
  549.  
  550.  
  551. // ---------------------------------------------------------------------------
  552. //        • Static Member Variable 
  553. // ---------------------------------------------------------------------------
  554.  
  555. Int16    LWindowMenuAttachment::sDecalItem = 0;
  556.  
  557.  
  558.  
  559. // ---------------------------------------------------------------------------
  560. //        • LWindowMenuAttachment
  561. // ---------------------------------------------------------------------------
  562.  
  563. LWindowMenuAttachment::LWindowMenuAttachment(
  564.     LWindow        *inWindow,
  565.     ResIDT        inWindowMenuID,
  566.     LDocument    *inDocument)
  567. {
  568.     mWindowMenuID = inWindowMenuID;
  569.     mWindow = inWindow;
  570.     mDocument = inDocument;
  571.     
  572.     
  573.     LMenu    *theMenu;
  574.             
  575.     // Find the menu
  576.     if((theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mWindowMenuID)) != nil) {
  577.     
  578.         Str255        itemText = "\p(-";    // A separator item
  579.         Int16        index = UWindowsUsher::GetWindowCount();
  580.         
  581.         
  582.         // Append a separator before the first window’s title
  583.         if((index == 1) ||
  584.            (CountMItems(theMenu->GetMacMenuH()) < sDecalItem)) {
  585.         
  586.             theMenu->InsertCommand(itemText, cmd_UseMenuItem, max_Int16 - 1);
  587.             sDecalItem = CountMItems(theMenu->GetMacMenuH());
  588.         }
  589.         
  590.         index = CountMItems(theMenu->GetMacMenuH()) + 1;
  591.         
  592.         inWindow->GetDescriptor(itemText);
  593.         
  594.         // Add a shortcut for the first 9 windows...
  595.         if((index - sDecalItem) <= 9) {
  596.         
  597.             Str255    tempString;
  598.             
  599.             ::NumToString(index - sDecalItem, tempString);
  600.             
  601.             ::ConcatPStr(itemText, "\p/");
  602.             ::ConcatPStr(itemText, tempString);
  603.         }
  604.         
  605.         theMenu->InsertCommand(itemText, cmd_UseMenuItem, max_Int16 - 1);
  606.         
  607.         // My command that I will have to manage...
  608.         mCmdToManage = theMenu->SyntheticCommandFromIndex(CountMItems(theMenu->GetMacMenuH()));
  609.     }
  610. }
  611.  
  612.  
  613. // ---------------------------------------------------------------------------
  614. //        • ~LWindowMenuAttachment
  615. // ---------------------------------------------------------------------------
  616.  
  617. LWindowMenuAttachment::~LWindowMenuAttachment()
  618. {
  619.     LMenu    *theMenu;
  620.     
  621.     
  622.     if((theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mWindowMenuID)) != nil) {
  623.     
  624.         theMenu->RemoveCommand(mCmdToManage);
  625.         
  626.         // If we were alone... clean up the Window Menu
  627.         if(UWindowsUsher::GetWindowCount() == 0) {
  628.         
  629.             theMenu->RemoveCommand(theMenu->SyntheticCommandFromIndex(sDecalItem));
  630.         }
  631.     }
  632. }
  633.  
  634.  
  635. // ---------------------------------------------------------------------------
  636. //        • AttachmentHasBeenRemoved
  637. // ---------------------------------------------------------------------------
  638.  
  639. void
  640. LWindowMenuAttachment::AttachmentHasBeenRemoved(
  641.     CommandT    inCommand)
  642. {
  643.     LMenu    *theMenu;
  644.     Int16    oldIndex = (Int16) (-mCmdToManage);
  645.     Int16    oldIndexRemoved = (Int16) (-inCommand);
  646.     
  647.     
  648.     
  649.     if(((theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mWindowMenuID)) != nil) &&
  650.         (oldIndex > oldIndexRemoved)) {
  651.     
  652.         mCmdToManage = theMenu->SyntheticCommandFromIndex(oldIndex - 1);
  653.         
  654.         if((oldIndex - sDecalItem) <= 10) {    // Our shortcut is downsizing...
  655.         
  656.             ::SetItemCmd(theMenu->GetMacMenuH(), oldIndex - 1, '0' + (oldIndex - 1 - sDecalItem));
  657.         
  658.         }
  659.     }
  660. }
  661.  
  662.  
  663. // ---------------------------------------------------------------------------
  664. //        • GetCommand
  665. // ---------------------------------------------------------------------------
  666.  
  667. CommandT
  668. LWindowMenuAttachment::GetCommand()
  669. {
  670.     return mCmdToManage;
  671. }
  672.  
  673.  
  674. // ---------------------------------------------------------------------------
  675. //        • ExecuteSelf
  676. // ---------------------------------------------------------------------------
  677.  
  678. void
  679. LWindowMenuAttachment::ExecuteSelf(
  680.     MessageT    inMessage,
  681.     void        *ioParam)
  682. {
  683.     mExecuteHost = true;
  684.     
  685.     
  686.     switch(inMessage) {
  687.     
  688.         case msg_CommandStatus:
  689.             SCommandStatusP        theCmdStatus = ((SCommandStatusP) ioParam);
  690.             
  691.             if(theCmdStatus->command == mCmdToManage) {
  692.                 
  693.                 // We use mark to show the active window!
  694.                 *theCmdStatus->usesMark = true;
  695.                 if(UDesktop::WindowIsSelected(mWindow)) {
  696.                 
  697.                     *theCmdStatus->mark = checkMark;
  698.                 
  699.                 } else {
  700.                 
  701.                     *theCmdStatus->mark = noMark;
  702.                 }
  703.                 
  704.                 // If document as been specified...
  705.                 if(mDocument != nil) {
  706.                     
  707.                     LMenu    *theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mWindowMenuID);
  708.                     Int16    index = theMenu->IndexFromCommand(mCmdToManage);
  709.                     
  710.                     
  711.                     if(mDocument->IsModified()) {
  712.                     
  713.                         // It should be underline...
  714.                         ::SetItemStyle(theMenu->GetMacMenuH(), index, underline);
  715.                     
  716.                     } else {
  717.                     
  718.                         // It shouldn’t be underline...
  719.                         ::SetItemStyle(theMenu->GetMacMenuH(), index, 0);
  720.                     }
  721.                     
  722.                 }
  723.                 
  724.                 // It may slowdown the execution, but it make change from
  725.                 // your window name transparent...
  726.                 mWindow->GetDescriptor(theCmdStatus->name);
  727.                 
  728.                 // Always enabled except if the front window is modal!
  729.                 *theCmdStatus->enabled = !UDesktop::FrontWindowIsModal();
  730.                 mExecuteHost = false;        // Don’t ask the host
  731.             
  732.             }
  733.             break;
  734.         
  735.         default:
  736.             if(inMessage == mCmdToManage) {
  737.             
  738.                                                 // Do our difficult job :-) !
  739.                 UDesktop::SelectDeskWindow(mWindow);
  740.                 mExecuteHost = false;            // Don’t ask the host
  741.             }
  742.             break;
  743.     }
  744. }
  745.  
  746.  
  747. // ===========================================================================
  748. // • LStackCmdAttachment                                 LStackCmdAttachment •
  749. // ===========================================================================
  750.  
  751.  
  752. // ---------------------------------------------------------------------------
  753. //        • ExecuteSelf
  754. // ---------------------------------------------------------------------------
  755.  
  756. void
  757. LStackCmdAttachment::ExecuteSelf(
  758.     MessageT    inMessage,
  759.     void        *ioParam)
  760. {
  761.     mExecuteHost = true;
  762.     
  763.     
  764.     switch(inMessage) {
  765.     
  766.         case msg_CommandStatus:
  767.             SCommandStatusP        theCmdStatus = ((SCommandStatusP) ioParam);
  768.             if(theCmdStatus->command == cmd_StackWindows) {
  769.             
  770.                 // Enable only if there is at least one window in the list!
  771. //                *theCmdStatus->enabled = true;//UWindowsUsher::IsStackEnabled();
  772.                 *theCmdStatus->enabled = UWindowsUsher::IsStackEnabled();
  773.                 mExecuteHost = false;        // Don’t ask the host
  774.             }
  775.             break;
  776.         
  777.         case cmd_StackWindows:
  778.             UWindowsUsher::Stack();            // Do our difficult job :-) !
  779.             mExecuteHost = false;            // Don’t ask the host
  780.             break;
  781.         
  782.     }
  783. }